﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace JSM.DataStore
{
	/// <summary>
	/// Factory for getting the default data store factory for a given type.
	/// </summary>
	public static class DefaultDataStoreFactory
	{
		/// <summary>
		/// Internal dictionary to store the instantiation functions for several types.
		/// </summary>
		private static readonly Dictionary<Type, Func<object, IDataStoreProvider>> _defaultDataStores = new Dictionary<Type, Func<object, IDataStoreProvider>>();

		/// <summary>
		/// Gets the default data store implementing the <see cref="IDataStoreProvider"/>-interface for the given object.
		/// </summary>
		/// <param name="javaScriptModelAware">
		/// The object to search for an default data store provider.
		/// </param>
		/// <returns>
		/// A data store provider implementing the <see cref="IDataStoreProvider"/>-interface.
		/// </returns>
		public static IDataStoreProvider GetDefaultDataStore(IJavaScriptModelAware javaScriptModelAware)
		{
			if (javaScriptModelAware == null)
				throw new ArgumentNullException("javaScriptModelAware");

			// Get the matching function for the given javaScriptModelAware and execute it with javaScriptModelAware as argument.
			// If no function was found, null will be returned.
			return (_defaultDataStores.Where(p => p.Key.IsInstanceOfType(javaScriptModelAware)).Select(p => p.Value(javaScriptModelAware))).FirstOrDefault();
		}

		/// <summary>
		/// Registers a function for instantiating the default data store provider implementing the <see cref="IDataStoreProvider"/>-interface for the given type.
		/// </summary>
		/// <param name="type">
		/// The type to register.
		/// </param>
		/// <param name="instantiationFunc">
		/// The function to instantiate the default data store provider implementing the <see cref="IDataStoreProvider"/>-interface.
		/// </param>
		public static void RegisterDefaultDataStore(Type type, Func<object, IDataStoreProvider> instantiationFunc)
		{
			if (type == null)
				throw new ArgumentNullException("type");
			if (instantiationFunc == null)
				throw new ArgumentNullException("instantiationFunc");

			_defaultDataStores[type] = instantiationFunc;
		}

		/// <summary>
		/// Unregisteres all default data stores.
		/// </summary>
		public static void UnregisterAllDefaultDataStores()
		{
			_defaultDataStores.Clear();
		}
	}
}
